#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

#define MAXNUM 1024

int clientFd[1024];
int serverFd;
int r=0;

void hand(int s)
{
    if (2==s)
    {
        //close 断开链接
        printf("bye bye\n");
        for (int i=0;i<MAXNUM;i++)
        {
            if (clientFd[i]!=-1)
            {
                close(clientFd[i]);
            }
        }

        close(serverFd);
        exit(1);
    }
}


void init()
{
    for (int i=0;i<MAXNUM;i++)
    {
        clientFd[i]=-1;
    }

    //创建socket
    serverFd = socket(AF_INET,SOCK_STREAM,0);
    if (-1==serverFd)
    {
        printf("创建socket失败\n");
        exit(-1);
    }
    printf("创建socket成功\n");

    //协议地址簇
    struct sockaddr_in addr={0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");//ip地址 注意字符串转网络字节序
    addr.sin_port=htons(4556);


    //绑定
    r = bind(serverFd,( struct sockaddr*)&addr,sizeof addr);

    if (-1==r)
    {
        printf("绑定失败:%m\n");
        close(serverFd);
        exit(-1);
    }
    printf("绑定成功\n");

    //监听
    r = listen(serverFd,100);
    if (-1==r)
    {
        printf("监听失败:%m\n");
        close(serverFd);
        exit(-1);
    }
    printf("监听成功\n");

    //接受客户端连接
    //
    // struct sockaddr_in cAddr = {0}; //用来接受客户端的协议地址簇
    // int len = sizeof cAddr;
}

void *handle_client(void *arg)
{
    char buff[1024];
    char temp[1024];
    int n=0;
    int* client  =(int*) arg;
    char temp[1024];
    while (1)
    {
        int r = recv(*client,buff,1023,0);
        if (r>0)
        {
            buff[r] = 0; //添加字符串结束符号
            printf("%d:%s\n",r,buff);

            //转发
            memset(temp,0,1024); //先清空
            sprintf(temp,"%d>>%s",*client,buff);

            for (int i=0;i<MAXNUM;i++)
            {
                if (-1!=clientFd[i])
                {
                    if (*client!=clientFd[i])
                    {
                        send(clientFd[i],temp,strlen(temp),0);
                    }
                }
            }

        }
    }
}


int main(){


    signal(2,hand);
    init();

    //接收客户端连接
    fd_set fds;
    int maxfd =0; //最大的描述符号
    maxfd = maxfd > serverFd ? maxfd:serverFd;
    while (1)
    {
        FD_ZERO(&fds);
        FD_SET(serverFd,&fds); //用来accept


        //客户端fd放进来
        for (int i=0;i<MAXNUM;i++)
        {
            if (-1!=clientFd[i])
            {
                FD_SET(clientFd[i],&fds);
                // maxfd = maxfd > clientFd[i] ? maxfd:clientFd[i];
            }
        }

        r =  select(maxfd+1,&fds,NULL,NULL,NULL);
        if (-1==r)
        {
            printf("服务器崩溃\n");
            hand(2);
        }else if (0==r)
        {
            printf("正在努力加载中 请稍后\n");
            continue;
        }else
        {
            //检查是否有客户端连接
            if (FD_ISSET(serverFd,&fds))
            {
                struct sockaddr_in cAddr = {0}; //用来接受客户端的协议地址簇
                int len = sizeof cAddr;
                int cfd = accept(serverFd,(struct sockaddr*)&cAddr,&len);
                if (-1==cfd)
                {
                    printf("客户端连接失败:%m\n");
                }else
                {
                    printf("有客户端连接上服务器：%d\n",cfd);
                    //保存客户端描述符号
                    for (int i=0;i<MAXNUM;i++)
                    {
                        if (-1==clientFd[i])
                        {
                            clientFd[i] = cfd;
                            maxfd = maxfd > clientFd[i] ? maxfd:clientFd[i];
                            break;
                        }
                    }
                }
            }

            //检查是否有客户端发送数据过来

            for (int i=0;i<MAXNUM;i++)
            {
                if (-1==clientFd[i] && FD_ISSET(clientFd[i],&fds))
                {
                    char buff[1024];
                    char temp[1024];
                    int len = recv(clientFd[i],buff,1023,0);
                    if (len >0 )
                    {
                        buff[len]=0;
                        printf("%d:%s\n",clientFd[i],buff);

                        memset(temp,0,1024);
                        //转发
                        sprintf(temp,"%d:%s",clientFd[i],buff);
                        printf("%s\n",temp);
                        for (int j=0;j<MAXNUM;j++)
                        {
                            if (-1==clientFd[j])
                            {
                                send(clientFd[i],temp,strlen(temp),0);
                            }
                        }
                    }else
                    {
                        printf("客户端%d断开链接\n",clientFd[i]);
                        clientFd[i]=-1;
                    }
                }
            }


        }
    }
}
